#ifndef CDISCRETE_ELEMENT_H
#define CDISCRETE_ELEMENT_H

#include "C3dValue.h"
#include <string.h>

namespace NApiCfd
{
    /**A class that can represent a sphere of a particle or a triangle mesh of a geometry; both of which are elements.*/
    class CDiscreteElement
    {
    public:
        /** Default constructor */
        CDiscreteElement()
        {
            m_elemID = -1;
            m_type[0]='\0';
            m_typeIndex = -1;

            NApiCfd::C3dValue m_pos(0.0, 0.0, 0.0);
            NApiCfd::C3dValue m_velocity(0.0, 0.0, 0.0);
            NApiCfd::C3dValue m_angVelocity(0.0, 0.0, 0.0);

            m_volume = 0.0;
            m_scale = 0.0;
            m_mass = 0.0;
            m_orientation[0] = 0.0;
            m_orientation[1] = 0.0;
            m_orientation[2] = 0.0;
            m_orientation[3] = 0.0;
        }

        /** Copy constructor */
        CDiscreteElement(const CDiscreteElement& element)
        {
            *this = element;
        }

        CDiscreteElement& operator=(const CDiscreteElement& rhs)
        {
            if(this != &rhs)
            {
                m_elemID = rhs.m_elemID;
                m_typeIndex = rhs.m_typeIndex;
                
                setType(rhs.m_type);

                m_pos = rhs.m_pos;
                m_velocity = rhs.m_velocity;
                m_angVelocity = rhs.m_angVelocity;
                m_volume = rhs.m_volume;
                m_scale = rhs.m_scale;
                m_mass = rhs.m_mass;

                m_orientation[0] = rhs.m_orientation[0];
                m_orientation[1] = rhs.m_orientation[1];
                m_orientation[2] = rhs.m_orientation[2];
                m_orientation[3] = rhs.m_orientation[3];
            }
            return *this;
        }

        virtual ~CDiscreteElement()
        {
            m_elemID = -1;
            m_type[0] = '\0';
            m_typeIndex = -1;
        }

        /**
         * Return the element ID 
         * @return Returns the element ID
         */
        int getElemID() {return m_elemID;};

        /**
         * Return the name of the particle type
         * @return type  The type of the particle human readable
         */
        char* getType() {return m_type;};

        /**
         * Return the type of the particle as an int identifier
         * @return Returns the type of the particle as an integer index
         */
        int getTypeIndex() const{return m_typeIndex;};

        /**
         * Return the particle position
         * @return Returns the position of the particle centroid as a 3dValue
         */
        NApiCfd::C3dValue getPosition() const{return m_pos;};

        /**
         * Return the particle velocity
         * @return Returns the velocity in 3d vector form
         */
        NApiCfd::C3dValue getVelocity() const{return m_velocity;};

        /**
         * Return the particle angular velocity
         * @return Returns the angVelocity the angular velocity in 3d vector form
         */
        NApiCfd::C3dValue getAngVelocity() const{return m_angVelocity;};

        /**
         * Return the particle volume
         * @return Returns the volume the particle
         */
        double getVolume() const{return m_volume;};

        /**
         * Return the particle scale
         * @return Returns the scale of the particle
         */
        double getScale() const{return m_scale;};
        
        /**
         * Return the particle mass
         * @return Returns the mass of the particle
         */
        double getMass() const{return m_mass;};

        /**
         * Return the orientation
         * @return Returns the particle orientation as a quaternion
         *         4 entry array of doubles
         */
        double* getOrientation() {return &m_orientation[0];};

        /**
         * Set the element ID 
         * @param elemID - The element ID
         */
        void setElemID(int elemID) { m_elemID = elemID;};

        /**
         * Set the name of the particle type
         * @param type - The name of the particle type
         */
        void setType(const char* type) { strncpy(m_type, type, MAX_TYPENAME_SZ - 1); m_type[MAX_TYPENAME_SZ - 1] = 0; };

        /**
         * Set the type of the particle by int
         * @param type - The type of the particle as an integer
         */
        void setTypeIndex(int type) {m_typeIndex = type;};

        /**
         * Set the particle position
         * @param pos - The 3d position of the particle
         */
        void setPosition(NApiCfd::C3dValue pos) {m_pos = pos;};

        /**
         * Set the particle velocity
         * @param vel - The velocity in 3d vector form
         */
        void setVelocity(NApiCfd::C3dValue vel) {m_velocity = vel;};

        /**
         * Set the particle angular velocity
         * @param angVel - The angular velocity in 3d vector form
         */
        void setAngVelocity(NApiCfd::C3dValue angVel) {m_angVelocity = angVel;};

        /**
         * Set the particle volume
         * @param vol - The particle volume
         */
        void setVolume(double vol) {m_volume = vol;};

        /**
         * Set the particle scale
         * @param scale - The scale of the particle
         */
        void setScale(double scale) {m_scale = scale;};
        
        /**
         * Set the mass of the particle
         * @param mass - The mass of the particle
         */
        void setMass(double mass) {m_mass = mass;};

        /**
         * Set the orientation
         * @param orientation - The orientation the particle orientation as 4 entry array quaternion
         */
        void setOrientation(double* orientation)
        {
            m_orientation[0] = orientation[0];
            m_orientation[1] = orientation[1];
            m_orientation[2] = orientation[2];
            m_orientation[3] = orientation[3];
        };


    protected:
        const static int MAX_TYPENAME_SZ = 64; /**< Maximum name for particle type */
        
        int m_elemID;
        char m_type[MAX_TYPENAME_SZ]; /**< Name of particle type */
        int m_typeIndex;

        NApiCfd::C3dValue m_pos;     /* particle position */
        NApiCfd::C3dValue m_velocity;
        NApiCfd::C3dValue m_angVelocity; /* Angular velocity */

        double m_volume;
        double m_scale;
        double m_mass;
        double m_orientation[4];/* A list of vectors to points within the particle */
    };
}

#endif // CDISCRETE_ELEMENT_H

